home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / mus / misc / play_handler_s.lzh / play-handler / play-handler.c < prev    next >
C/C++ Source or Header  |  1995-01-26  |  15KB  |  557 lines

  1. /* playhandler: sowas wie /dev/audio fuer sparks
  2.    Mountlist:
  3.  
  4.    Handler     = L:PlayHandler
  5.    Priority    = 5
  6.    Stacksize   = 1000
  7.    GlobVec     = -1
  8. */
  9.  
  10. #ifdef LATTICE
  11. #define __USE_SYSBASE
  12. #endif
  13.  
  14. #include <dos/dos.h>
  15. #include <dos/dosextens.h>
  16. #include <dos/filehandler.h>
  17. #include <devices/audio.h>
  18. #include <exec/execbase.h>
  19. #include <exec/memory.h>
  20. #include <graphics/gfxbase.h>
  21. #include <clib/exec_protos.h>
  22. #include <clib/dos_protos.h>
  23. #include <clib/alib_protos.h>
  24. #include <stdlib.h>
  25. #include <ctype.h>
  26.  
  27. #define BUFLEN 512
  28. #define BUFFERS 20
  29. #define SAMPLES 8192
  30.  
  31. #define MIN(A,B) (((A)<(B))?(A):(B))
  32.  
  33. struct VHDR {
  34. ULONG oneShotHiSamples,repeatHiSamples,samplesPerHiCycle;
  35. UWORD samplesPerSec;
  36. UBYTE ctOctave,sCompression;
  37. LONG volume;
  38. };
  39.  
  40. enum parserstates {init,vhdr,readover,body,no8svx,identifyhunk};
  41.  
  42. struct streaminfo {
  43. UBYTE *buf[2];
  44. ULONG buflen;
  45. struct IOAudio req[5];
  46. char which;
  47. char deflt;
  48. char played[2];
  49. ULONG cnt;
  50. UWORD samples;
  51. char channel;
  52. UBYTE parsebuf[sizeof(struct VHDR)];
  53. UBYTE bufcnt;
  54. ULONG chunkcnt;
  55. enum parserstates parserstate;
  56. };
  57.  
  58. struct DosPacket *getpacket(struct MsgPort *);
  59. void replypacket(struct DosPacket *,LONG,LONG);
  60. LONG playhandler(void);
  61. void playpacket(struct streaminfo *,APTR,LONG);
  62. void parsepacket(struct DosPacket *);
  63. int openstream(struct DosPacket *);
  64. #ifdef LATTICE
  65. void geta4(void);
  66. #endif
  67. char *BSTR2C(char *);
  68. void parsename(struct streaminfo *,LONG);
  69.  
  70. extern struct ExecBase *
  71. #ifdef LATTICE
  72.                          __far
  73. #endif
  74.                                 AbsExecBase;
  75.  
  76. struct ExecBase *SysBase;
  77. struct GfxBase *GfxBase;
  78. struct DosLibrary *DOSBase;
  79. LONG dmaclock;
  80. LONG buffers;
  81.  
  82. static char version[]="$VER: PLAY-Handler V1.00 by JD - "
  83. #ifdef SHARE
  84. "Shareware Version"
  85. #else
  86. "Full Version licenced to "
  87. "Joerg Dorchain"
  88. #endif
  89. ;
  90.  
  91. /* saveds ??*/
  92.  
  93. LONG playhandler()
  94. {
  95. struct MsgPort *pp;
  96. struct DosPacket *dp;
  97. struct Process *me;
  98. struct streaminfo *sip;
  99. struct DeviceNode *dn,**pdn,*dn2;
  100. struct DosInfo *di;
  101. int die;
  102. int open;
  103.  
  104. #ifdef LATTICE
  105. geta4();
  106. #endif
  107.  
  108. SysBase=AbsExecBase;
  109.  
  110. me=(struct Process *)SysBase->ThisTask;
  111. if (me->pr_CLI!=NULL)
  112.   return 5;
  113. pp=&me->pr_MsgPort;
  114.  
  115. WaitPort(pp);
  116. dp=getpacket(pp);
  117. dn=((struct DeviceNode *)BADDR(dp->dp_Arg3));
  118. dn->dn_Task=pp;
  119. replypacket(dp,DOSTRUE,0);
  120.  
  121. die=0;
  122. open=0;
  123. buffers=BUFFERS;
  124. dmaclock=3579545;
  125. if ((GfxBase=(struct GfxBase *)OpenLibrary("graphics.library",0))!=NULL)
  126.  {
  127.   if ((GfxBase->DisplayFlags&PAL)==NULL)
  128.     dmaclock=357945;
  129.   CloseLibrary((struct Library *)GfxBase);
  130.  }
  131.  
  132. for(;;)
  133.  {
  134.   WaitPort(pp);
  135.   if ((dp=getpacket(pp))!=NULL)
  136.    {
  137.     switch(dp->dp_Type)
  138.      {
  139.       case ACTION_FINDUPDATE:
  140.       case ACTION_FINDINPUT:
  141.       case ACTION_FINDOUTPUT:
  142.         if ((die==1)
  143. #ifdef SHARE
  144.                    ||(open==1)
  145. #endif
  146.                               )
  147.           replypacket(dp,DOSFALSE,ERROR_OBJECT_IN_USE);
  148.         else
  149.           if(openstream(dp)==1)
  150.            {
  151.             open++;
  152. #ifdef SHARE
  153.             die=1;
  154. #endif
  155.            }
  156.         break;
  157.       case ACTION_END:
  158.         sip=(struct streaminfo *)dp->dp_Arg1;
  159.         if (sip->cnt!=0)
  160.          {
  161.           sip->req[sip->which].ioa_Request.io_Command=
  162.           sip->req[sip->which+2].ioa_Request.io_Command=CMD_WRITE;
  163.           sip->req[sip->which].ioa_Request.io_Flags=
  164.           sip->req[sip->which+2].ioa_Request.io_Flags=ADIOF_PERVOL;
  165.           sip->req[sip->which].ioa_Data=
  166.           sip->req[sip->which+2].ioa_Data=sip->buf[sip->which];
  167.           sip->req[sip->which].ioa_Length=
  168.           sip->req[sip->which+2].ioa_Length=sip->cnt;
  169.           sip->req[sip->which].ioa_Period=
  170.           sip->req[sip->which+2].ioa_Period=dmaclock/sip->samples;
  171.           sip->req[sip->which].ioa_Volume=
  172.           sip->req[sip->which+2].ioa_Volume=64;
  173.           sip->req[sip->which].ioa_Cycles=
  174.           sip->req[sip->which+2].ioa_Cycles=1;
  175.           if ((sip->channel==1)&&((sip->played[0]|sip->played[1])==0))
  176.            {
  177.             sip->req[4].ioa_Request.io_Command=CMD_STOP;
  178.             DoIO((struct IORequest *)&sip->req[4]);
  179.            }
  180.           BeginIO((struct IORequest *)&sip->req[sip->which]);
  181.           if (sip->channel==1)
  182.            {
  183.             BeginIO((struct IORequest *)&sip->req[sip->which+2]);
  184.             if ((sip->played[0]|sip->played[1])==0)
  185.              {
  186.               sip->req[4].ioa_Request.io_Command=CMD_START;
  187.               DoIO((struct IORequest *)&sip->req[4]);
  188.              }
  189.            }
  190.           WaitIO((struct IORequest *)&sip->req[sip->which]);
  191.           if (sip->channel==1)
  192.             WaitIO((struct IORequest *)&sip->req[sip->which+2]);
  193.          }
  194.         sip->req[4].ioa_Request.io_Command=CMD_RESET;
  195.         DoIO((struct IORequest *)&sip->req[4]);
  196.         CloseDevice((struct IORequest *)&sip->req[4]);
  197.         DeletePort(sip->req[0].ioa_Request.io_Message.mn_ReplyPort);
  198.         FreeMem(sip->buf[1],sip->buflen);
  199.         FreeMem(sip->buf[0],sip->buflen);
  200.         FreeMem(sip,sizeof(struct streaminfo));
  201.         open--;
  202.         replypacket(dp,DOSTRUE,0);
  203.         break;
  204.       case ACTION_READ:
  205.       case ACTION_SEEK:
  206.       case ACTION_SET_FILE_SIZE:
  207.         replypacket(dp,-1,ERROR_ACTION_NOT_KNOWN);
  208.         break;
  209.       case ACTION_WRITE:
  210.         parsepacket(dp);
  211.         replypacket(dp,dp->dp_Arg3,0);
  212.         break;
  213.       case ACTION_IS_FILESYSTEM:
  214.         replypacket(dp,0,0);
  215.         break;
  216.       case ACTION_DIE:
  217.         die=1;
  218.         replypacket(dp,DOSTRUE,0);
  219.         break;
  220.       case ACTION_MORE_CACHE:
  221.         buffers+=dp->dp_Arg1;
  222.         if(buffers<1)
  223.           buffers=1;
  224.         replypacket(dp,buffers,buffers);
  225.         break;
  226.       default:
  227.         replypacket(dp,DOSFALSE,ERROR_ACTION_NOT_KNOWN);
  228.         break;
  229.      }
  230.    }
  231.   if ((open==0)&&(die==1))
  232.    {
  233.     if ((DOSBase=(struct DosLibrary *)OpenLibrary("dos.library",0))!=NULL)
  234.      {
  235.       if (DOSBase->dl_lib.lib_Version>36)
  236.         LockDosList(LDF_WRITE|LDF_ALL|LDF_DELETE);
  237.       di=BADDR(((struct RootNode *)DOSBase->dl_Root)->rn_Info);
  238.       pdn=(struct DeviceNode **)&di->di_DevInfo;
  239.       Forbid();
  240.       while((dn2=BADDR(*pdn))!=dn)
  241.         pdn=(struct DeviceNode **)&dn2->dn_Next;
  242.       *pdn=(struct DeviceNode *)dn->dn_Next;
  243.       UnLoadSeg(dn->dn_SegList);
  244.       FreeMem(BADDR(dn->dn_Name),((UBYTE *)BADDR(dn->dn_Name))[0]+1);
  245.       FreeMem(BADDR(dn->dn_Handler),((UBYTE *)BADDR(dn->dn_Handler))[0]+1);
  246.       FreeMem(dn,sizeof(struct DeviceNode));
  247.       if (DOSBase->dl_lib.lib_Version>36)
  248.         UnLockDosList(LDF_WRITE|LDF_ALL|LDF_DELETE);
  249.       while((dp=getpacket(pp))!=NULL)
  250.         replypacket(dp,-1,ERROR_DEVICE_NOT_MOUNTED);
  251.       return 0;
  252.      }
  253.     die=0;
  254.    }
  255.  }
  256. }
  257.  
  258. struct DosPacket *getpacket(mp)
  259. struct MsgPort *mp;
  260. {
  261. struct Message *mn;
  262.  
  263. if ((mn=GetMsg(mp))==NULL)
  264.   return NULL;
  265. return (struct DosPacket *)mn->mn_Node.ln_Name;
  266. }
  267.  
  268. void replypacket(dp,arg1,arg2)
  269. struct DosPacket *dp;
  270. LONG arg1,arg2;
  271. {
  272. struct MsgPort *mp;
  273. struct Message *mn;
  274.  
  275. mp=dp->dp_Port;
  276. mn=dp->dp_Link;
  277.  
  278. mn->mn_Node.ln_Name=(char *)dp;
  279. dp->dp_Port=&((struct Process *)SysBase->ThisTask)->pr_MsgPort;
  280. dp->dp_Res1=arg1;
  281. dp->dp_Res2=arg2;
  282.  
  283. PutMsg(mp,mn);
  284. }
  285.  
  286. void playpacket(sip,buf,len)
  287. struct streaminfo *sip;
  288. APTR buf;
  289. LONG len;
  290. {
  291. LONG cnt2;
  292.  
  293.  cnt2=0;
  294.  while(sip->buflen-sip->cnt<=len-cnt2)
  295.   {
  296.    CopyMem(((UBYTE *)buf)+cnt2,
  297.            ((UBYTE *)sip->buf[sip->which])+sip->cnt,
  298.            sip->buflen-sip->cnt);
  299.    sip->req[sip->which].ioa_Request.io_Command=
  300.      sip->req[sip->which+2].ioa_Request.io_Command=CMD_WRITE;
  301.    sip->req[sip->which].ioa_Request.io_Flags=
  302.      sip->req[sip->which+2].ioa_Request.io_Flags=ADIOF_PERVOL;
  303.    sip->req[sip->which].ioa_Data=
  304.      sip->req[sip->which+2].ioa_Data=sip->buf[sip->which];
  305.    sip->req[sip->which].ioa_Length=
  306.      sip->req[sip->which+2].ioa_Length=sip->buflen;
  307.    sip->req[sip->which].ioa_Period=
  308.      sip->req[sip->which+2].ioa_Period=dmaclock/sip->samples;
  309.    sip->req[sip->which].ioa_Volume=
  310.      sip->req[sip->which+2].ioa_Volume=64;
  311.    sip->req[sip->which].ioa_Cycles=
  312.      sip->req[sip->which+2].ioa_Cycles=1;
  313.    if ((sip->channel==1)&&((sip->played[0]|sip->played[1])==0))
  314.     {
  315.      sip->req[4].ioa_Request.io_Command=CMD_STOP;
  316.      DoIO((struct IORequest *)&sip->req[4]);
  317.     }
  318.    BeginIO((struct IORequest *)&sip->req[sip->which]);
  319.    if (sip->channel==1)
  320.     {
  321.      BeginIO((struct IORequest *)&sip->req[sip->which+2]);
  322.      if ((sip->played[0]|sip->played[1])==0)
  323.       {
  324.        sip->req[4].ioa_Request.io_Command=CMD_START;
  325.        DoIO((struct IORequest *)&sip->req[4]);
  326.       }
  327.     }
  328.    sip->played[sip->which]=1;
  329.    cnt2+=sip->buflen-sip->cnt;
  330.    sip->which=1-sip->which;
  331.    sip->cnt=0;
  332.    if (sip->played[sip->which]==1)
  333.     {
  334.      WaitIO((struct IORequest *)&sip->req[sip->which]);
  335.      if (sip->channel==1)
  336.        WaitIO((struct IORequest *)&sip->req[sip->which+2]);
  337.      sip->played[sip->which]=0;
  338.     }
  339.   }
  340.  CopyMem(((UBYTE *)buf)+cnt2,
  341.          ((UBYTE *)sip->buf[sip->which])+sip->cnt,
  342.          len-cnt2);
  343.  sip->cnt+=len-cnt2;
  344. }
  345.  
  346. void parsepacket(dp)
  347. struct DosPacket *dp;
  348. {
  349. struct streaminfo *sip;
  350. LONG cnt2;
  351. LONG min;
  352. ULONG ident;
  353.  
  354. sip=(struct streaminfo *)dp->dp_Arg1;
  355. cnt2=0;
  356. while(dp->dp_Arg3>cnt2)
  357.  {
  358.   switch (sip->parserstate)
  359.    {
  360.     case no8svx:
  361.       playpacket(sip,((UBYTE *)dp->dp_Arg2)+cnt2,dp->dp_Arg3-cnt2);
  362.       cnt2=dp->dp_Arg3;
  363.       break;
  364.     case init:
  365.       min=MIN(12-sip->bufcnt,dp->dp_Arg3-cnt2);
  366.       CopyMem(((UBYTE *)dp->dp_Arg2)+cnt2,
  367.               sip->parsebuf+sip->bufcnt,
  368.               min);
  369.       cnt2+=min;
  370.       sip->bufcnt+=min;
  371.       if (sip->bufcnt==12)
  372.        {
  373.          if((*(ULONG *)sip->parsebuf==0x464f524d)&&
  374.             (*(ULONG *)(sip->parsebuf+8)==0x38535658))
  375.            sip->parserstate=identifyhunk;
  376.          else
  377.           {
  378.            sip->parserstate=no8svx;
  379.            playpacket(sip,sip->parsebuf,12);
  380.           }
  381.          sip->bufcnt=0;
  382.         }
  383.        break;
  384.      default: /*identify,vhdr,body,readover*/
  385.        if ((sip->parserstate==identifyhunk)||(sip->chunkcnt==0))
  386.         {
  387.          min=MIN(4-sip->bufcnt,dp->dp_Arg3-cnt2);
  388.          CopyMem(((UBYTE *)dp->dp_Arg2)+cnt2,
  389.               sip->parsebuf+sip->bufcnt,
  390.               min);
  391.          cnt2+=min;
  392.          sip->bufcnt+=min;
  393.          if (sip->bufcnt==4)
  394.           {
  395.            sip->bufcnt=0;
  396.            ident=*(ULONG *)sip->parsebuf;
  397.            if (sip->parserstate==identifyhunk)
  398.             {
  399.              switch (ident)
  400.               {
  401.                case 0x464f524d: /*FORM*/
  402.                  sip->parserstate=init;
  403.                  sip->bufcnt=4;
  404.                  break;
  405.                case 0x56484452: /*VHDR*/
  406.                  sip->parserstate=vhdr;
  407.                  break;
  408.                case 0x424f4459: /*BODY*/
  409.                  sip->parserstate=body;
  410.                  break;
  411.                default:
  412.                  sip->parserstate= readover;
  413.                  break;
  414.               }
  415.             }
  416.            else
  417.              sip->chunkcnt=ident+ident%2;
  418.           }
  419.         }
  420.        else
  421.         {
  422.          min=MIN(sip->chunkcnt,dp->dp_Arg3-cnt2);
  423.          switch(sip->parserstate)
  424.           {
  425.            case vhdr:
  426.              CopyMem(((UBYTE *)dp->dp_Arg2)+cnt2,
  427.                      sip->parsebuf+sip->bufcnt,
  428.                      min);
  429.              sip->bufcnt+=min;
  430.              if (sip->bufcnt==sizeof(struct VHDR))
  431.               {
  432.                if (sip->deflt==1)
  433.                  sip->samples=((struct VHDR *)sip->parsebuf)->samplesPerSec;
  434.                sip->bufcnt=0;
  435.               }
  436.              break;
  437.            case body:
  438.              playpacket(sip,((UBYTE *)dp->dp_Arg2)+cnt2,min);
  439.              break;
  440.           }
  441.          sip->chunkcnt-=min;
  442.          cnt2+=min;
  443.          if (sip->chunkcnt==0)
  444.            sip->parserstate=identifyhunk;
  445.         }
  446.        break;
  447.    }
  448.  }
  449. }
  450.  
  451. int openstream(dp)
  452. struct DosPacket *dp;
  453. {
  454. struct streaminfo *sip;
  455. struct MsgPort *mp;
  456. struct FileHandle *fh;
  457. static UBYTE channel0[]={2,4,1,8};
  458. static UBYTE channel1[]={3,5,10,12};
  459. static UBYTE *channels[4]= {channel0,channel1,channel0,channel0+2};
  460. /*  egal, stereo, left, right */
  461. union {
  462. ULONG channel;
  463. APTR ptr;
  464. } unit;
  465.  
  466. if ((sip=AllocMem(sizeof(struct streaminfo),MEMF_ANY|MEMF_CLEAR))!=NULL)
  467. {
  468.   sip->buflen=buffers*BUFLEN;
  469.   if ((sip->buf[0]=AllocMem(sip->buflen,MEMF_CHIP))!=NULL)
  470.    {
  471.     if ((sip->buf[1]=AllocMem(sip->buflen,MEMF_CHIP))!=NULL)
  472.      {
  473.       if ((mp=CreatePort("",0))!=NULL)
  474.        {
  475.         parsename(sip,dp->dp_Arg3);
  476.         sip->req[0].ioa_Request.io_Message.mn_Node.ln_Type=NT_MESSAGE;
  477.         sip->req[0].ioa_Request.io_Message.mn_Length=sizeof(struct IOAudio);
  478.         sip->req[0].ioa_Request.io_Message.mn_ReplyPort=mp;
  479.         sip->req[0].ioa_Request.io_Command=ADCMD_ALLOCATE;
  480.         sip->req[0].ioa_Request.io_Flags=ADIOF_NOWAIT;
  481.         sip->req[0].ioa_Data=channels[sip->channel];
  482.         sip->req[0].ioa_Length=(sip->channel<2)?4:2;
  483.         sip->req[0].ioa_Request.io_Message.mn_Node.ln_Pri=75;
  484.         Forbid();
  485.         if (OpenDevice("audio.device",0,(struct IORequest *)&sip->req[0],0)==NULL)
  486.          {
  487.           sip->req[0].ioa_Request.io_Message.mn_Node.ln_Pri=127;
  488.           sip->req[0].ioa_Request.io_Command=ADCMD_SETPREC;
  489.           DoIO((struct IORequest *)&sip->req[0]);
  490.           Permit();
  491.           sip->req[4]=sip->req[1]=sip->req[0];
  492.           if (sip->channel==1)
  493.            {
  494.             sip->req[3]=sip->req[2]=sip->req[0];
  495.             unit.ptr=sip->req[4].ioa_Request.io_Unit;
  496.             unit.channel&=6;
  497.             sip->req[0].ioa_Request.io_Unit=
  498.               sip->req[1].ioa_Request.io_Unit=unit.ptr;
  499.             unit.ptr=sip->req[4].ioa_Request.io_Unit;
  500.             unit.channel&=9;
  501.             sip->req[2].ioa_Request.io_Unit=
  502.               sip->req[3].ioa_Request.io_Unit=unit.ptr;
  503.            }
  504.           sip->parserstate=init;
  505.           fh=(struct FileHandle *)BADDR(dp->dp_Arg1);
  506.           fh->fh_Arg1=(LONG)sip;
  507.           replypacket(dp,DOSTRUE,0);
  508.           return 1;
  509.          }
  510.         Permit();
  511.         DeletePort(mp);
  512.        }
  513.       FreeMem(sip->buf[1],sip->buflen);
  514.      }
  515.     FreeMem(sip->buf[0],sip->buflen);
  516.    }
  517.   FreeMem(sip,sizeof(struct streaminfo));
  518.  }
  519. replypacket(dp,DOSFALSE,ERROR_NO_FREE_STORE);
  520. return 0;
  521. }
  522.  
  523. char *BSTR2C(bstr)
  524. char *bstr;
  525. {
  526. static char cstr[256];
  527. int i;
  528.  
  529. bstr=BADDR(bstr);
  530. for(i=0;i<=bstr[0];i++)
  531.  cstr[i]=bstr[i+1];
  532. cstr[i]=0;
  533. return cstr;
  534. }
  535.  
  536. void parsename(sip,bstr)
  537. struct streaminfo *sip;
  538. LONG bstr;
  539. {
  540. char *fn;
  541.  
  542. fn=BSTR2C((char *)bstr);
  543. while(*(fn++)!=':');
  544. *fn=tolower(*fn);
  545. if ((*fn=='s')||(*fn=='l')||(*fn=='r'))
  546.  {
  547.   sip->channel=(*fn=='s')?1:(*fn=='l')?2:3;
  548.   fn++;
  549.  }
  550. if ((sip->samples=atol(fn))==0)
  551.  {
  552.   sip->deflt=1;
  553.   sip->samples=SAMPLES;
  554.  }
  555. }
  556.  
  557.